package org.tulkas.robot.base;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import javax.sql.DataSource;

import org.tulkas.robot.exception.SystemException;
import org.tulkas.util.Converter;
import org.tulkas.util.FileUtil;

import com.mchange.v2.c3p0.ComboPooledDataSource;

/**
 * @author <a href="mailto:tulkas.web@gmail.com">Tulkas</a>
 *
 */
public final class PersistenceHelper {
	public static final String DERBY_JDBC_PREFIX = "jdbc:derby:";

	private PersistenceHelper() {
	}

	public static DataSource initC3p0DataSource(
			ComboPooledDataSource dataSource, Properties props) {
		String str = null;
		str = props.getProperty("jdbcUrl");
		if (str != null) {
			dataSource.setJdbcUrl(str.trim());
		}

		str = props.getProperty("user");
		if (str != null) {
			dataSource.setUser(str.trim());
		}
		str = props.getProperty("password");
		if (str != null) {
			dataSource.setPassword(str.trim());
		}

		str = props.getProperty("minPoolSize");
		if (str != null) {
			dataSource.setMinPoolSize(Converter.toInt(str.trim()));
		}

		str = props.getProperty("maxPoolSize");
		if (str != null) {
			dataSource.setMaxPoolSize(Converter.toInt(str.trim()));
		}

		str = props.getProperty("initialPoolSize");
		if (str != null) {
			dataSource.setInitialPoolSize(Converter.toInt(str.trim()));
		}

		str = props.getProperty("maxIdleTime");
		if (str != null) {
			dataSource.setMaxIdleTime(Converter.toInt(str.trim()));
		}

		str = props.getProperty("acquireIncrement");
		if (str != null) {
			dataSource.setAcquireIncrement(Converter.toInt(str.trim()));
		}

		str = props.getProperty("acquireRetryAttempts");
		if (str != null) {
			dataSource.setAcquireRetryAttempts(Converter.toInt(str.trim()));
		}

		str = props.getProperty("acquireRetryDelay");
		if (str != null) {
			dataSource.setAcquireRetryDelay(Converter.toInt(str.trim()));
		}

		str = props.getProperty("testConnectionOnCheckin");
		if (str != null) {
			dataSource.setTestConnectionOnCheckin(Converter.toBoolean(str
					.trim()));
		}

		str = props.getProperty("automaticTestTable");
		if (str != null) {
			dataSource.setAutomaticTestTable(str.trim());
		}

		str = props.getProperty("idleConnectionTestPeriod");
		if (str != null) {
			dataSource.setIdleConnectionTestPeriod(Converter.toInt(str.trim()));
		}

		str = props.getProperty("checkoutTimeout");
		if (str != null) {
			dataSource.setCheckoutTimeout(Converter.toInt(str.trim()));
		}

		return dataSource;
	}

	public static void initDerbyDriver() throws Exception {
		Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
		System.setProperty("derby.system.home", GlobalConfig.getInstance()
				.getHomePath()
				+ "/derby");
	}

	public static String getDerbyJdbcUrl(String dbPath) {
		return DERBY_JDBC_PREFIX + FileUtil.trimFilePath(dbPath);
	}

	public static boolean ensureDerbyDBCreated(String dbPath) {
		Connection conn = null;
		String jdbcUrl = null;
		try {
			jdbcUrl = getDerbyJdbcUrl(dbPath);
			conn = DriverManager.getConnection(jdbcUrl);
			return true;
		} catch (SQLException e) {
			jdbcUrl = getDerbyJdbcUrl(dbPath) + ";create=true";
			try {
				conn = DriverManager.getConnection(jdbcUrl);
			} catch (SQLException e1) {
				throw new SystemException(
						"Error initializing Derby database in [" + dbPath + "]",
						e1);
			}
			return false;
		} finally {
			tryToClose(null, null, conn);
		}
	}

	public static void tryToClose(ResultSet rs) {
		tryToClose(rs, null, null);
	}

	public static void tryToClose(ResultSet rs, Statement stmt) {
		tryToClose(rs, stmt, null);
	}

	public static void tryToClose(ResultSet rs, Statement stmt, Connection conn) {
		try {
			if (rs != null)
				rs.close();
			if (stmt != null)
				stmt.close();
			if (conn != null)
				conn.close();
		} catch (SQLException e) {
			throw new SystemException(e);
		}
	}
}
